package com.fishery.customization.service.impl;

import com.fishery.customization.dao.LabelDao;
import com.fishery.customization.entity.ConstantValue;
import com.fishery.customization.entity.Label;
import com.fishery.customization.entity.OneLevelLabel;
import com.fishery.customization.service.FixedLabelService;
import com.fishery.customization.service.FunctionLabelService;
import com.fishery.customization.service.LabelService;
import com.fishery.customization.service.UserLabelService;
import com.fishery.customization.service.client.AuthorityClient;
import com.fishery.customization.util.DataUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.*;

@Service
public class LabelServiceImpl implements LabelService {

	@Autowired
	private LabelDao labelDao;

	@Autowired
	private FixedLabelService fixedLabelService;

	@Autowired
	private FunctionLabelService functionLabelService;

	@Autowired
	private UserLabelService userLabelService;

	@Autowired
	private AuthorityClient authorityClient;

	@Autowired
	private ExecutorService threadPool;

	@Value("${fishery.role}")
	private String DEFAULT_ROLE;


	@Override
	public String getLabelsJsonByBaseIdAndRoleAndUserId(String baseId, String role, String userId) {
		// 待返回待Json
		String retJson = null;
		// 先获取用户自定义后的标签
		retJson = userLabelService.getCustomizedLabelsOfUserByUserId(userId);
		// 判断用户是否有自定义标签
		if (StringUtils.isEmpty(retJson)) {
			// 用户没有自定义标签，则需要返回原来的标签
			retJson = labelDao.findLabelJsonByBaseIdAndRole(baseId, role);
		}
		return retJson;
	}

	private boolean addLabelInMap(OneLevelLabel oneLevelLabel, Map<String, OneLevelLabel> target) {
		Assert.notNull(oneLevelLabel, "oneLevelLabel must not be null");
		Assert.notNull(target, "target must not be null");
		OneLevelLabel labelInMap = target.get(oneLevelLabel.getName());
		if (labelInMap == null) {
			target.put(oneLevelLabel.getName(), oneLevelLabel);
		} else {
			labelInMap.getChildren().addAll(oneLevelLabel.getChildren());
		}
		return true;
	}

	@Override
	public boolean updateLabelsForRoleOfBase(String baseId, String role, Map<String, String> functionMap) {
		// 通过权限名映射到标签上,并组装
		Map<String, OneLevelLabel> deleteLabelsMap = new HashMap<>(4);
		Map<String, OneLevelLabel> addLabelsMap = new HashMap<>(4);
		// 获取要修改的权限名
		Set<String> functionNames = functionMap.keySet();
		// 进行组装，当二级标签为null时，也要构造出一级标签
		functionNames.forEach(functionName -> {
			// 通过权限名映射出一级标签
			OneLevelLabel oneLevelLabel = functionLabelService.getOneLevelLabelByFunctionName(functionName);
			if (functionMap.get(functionName).equals("1")) {
				// 新增
				addLabelInMap(oneLevelLabel, addLabelsMap);
			} else {
				// 删除
				addLabelInMap(oneLevelLabel, deleteLabelsMap);
			}
		});
		// 对基地角色标签进行进行更新
		threadPool.submit(() -> {
			labelDao.queryAndUpdate(baseId, role, addLabelsMap.values(), deleteLabelsMap.values());
		});

		// 对用户自定义对标签进行进行更新
		threadPool.submit(() -> {
			userLabelService.updateUserLabelsByBaseIdAndRole(baseId, role,
					addLabelsMap.values(), deleteLabelsMap.values());
		});
		return true;
	}


	@Override
	public boolean createLabelsOfBase(String baseId, List<String> types) {
		// 基地标签进行保存操作
		// 添加最基本到固定标签类型
		types.add(ConstantValue.LABEL_BASIC_TYPE);
		// 获取到所有到固定标签（含最基础到固定标签）
		List<OneLevelLabel> labels = fixedLabelService.findAllFixedLabels(types);
		// 删除最基本固定标签类型（不想让其进行保存）
		types.remove(ConstantValue.LABEL_BASIC_TYPE);
		// 将固定标签、固定标签类型、基地id、默认老板角色，保存到mongo
		return labelDao.insert(new Label(DEFAULT_ROLE, types, baseId, labels)) > 0;
	}

	@Override
	public boolean extendLabelsOfBase(String baseId, List<String> types) {
		// 查出基地类型，检测是否输入的types有问题
		List<String> baseTypes = labelDao.findTypesByBaseId(baseId);
		for (String type : types) {
			if (baseTypes.contains(type)) {
				return false;
			}
		}
		boolean flag = false;
		// 查询出要拓展的标签
		List<OneLevelLabel> labels = fixedLabelService.findAllFixedLabels(types);
		// 进行去重处理
		DataUtil.exceptSameLabels(labelDao.findLabelByBaseIdAndRole(baseId, DEFAULT_ROLE).getLabels(), labels);
		flag = true;
		if (flag) {
			List<OneLevelLabel> copyLabels = (List<OneLevelLabel>) DataUtil.copyObjectDeeply(labels);
			// 对老板相关信息进行维护
			threadPool.submit(() -> {
				// 对老板权限进行维护更新
				String oldTypes = DataUtil.getRedisKey(baseTypes);
				baseTypes.addAll(types);
				String newTypes = DataUtil.getRedisKey(baseTypes);
				authorityClient.updateBaseAdmin(baseId, oldTypes, newTypes);
				// 基地老板角色进行拓展
				labelDao.extend(baseId, DEFAULT_ROLE, labels);
				// 对老板自定义标签进行拓展
				userLabelService.updateUserLabelsByBaseIdAndRole(baseId, DEFAULT_ROLE, labels, null);
			});

			// 基地其它角色标签进行慢拓展
			threadPool.submit(() -> {
				// 去除拓展的一级标签中需要权限的二级标签
				DataUtil.exceptSameLabels(functionLabelService.getAllOneLevelLabels(), copyLabels);
				// 进行拓展
				labelDao.extendExceptThisRole(baseId, DEFAULT_ROLE, copyLabels);
				// 对其他角色的用户自定义标签进行拓展
				userLabelService.updateOtherUsersLabelsOfBaseByBaseIdAndRole(baseId, DEFAULT_ROLE, copyLabels, null);
			});

			// 对基地类型进行更新
			threadPool.submit(() -> {
				labelDao.updateTypesOfBase(baseId, types);
			});

		}
		return flag;
	}


	@Override
	public List<String> getTypesOfBase(String baseId) {
		return labelDao.findTypesByBaseId(baseId);
	}

	@Override
	public boolean createLabelsForRoleOfBase(String baseId, String role) {
		// 查出基地老板的所有一级标签
		Label label = labelDao.findLabelByBaseIdAndRole(baseId, DEFAULT_ROLE);
		// 去除一级标签中需要权限的二级标签
		DataUtil.exceptSameLabels(functionLabelService.getAllOneLevelLabels(), label.getLabels());
		// 设置label角色名
		label.setRole(role);
		label.setId(null);
		return labelDao.insert(label) > 0;
	}

	@Override
	public boolean updateNameOfBaseRoleByBaseId(String baseId, String oldName, String newName) {
		threadPool.submit(() -> {
			labelDao.updateBaseRoleNameByBaseId(baseId, oldName, newName);
		});
		threadPool.submit(() -> {
			userLabelService.updateBaseRoleNameByBaseId(baseId, oldName, newName);
		});
		return true;
	}

	@Override
	public String getLabelsJsonByBaseIdAndRole(String baseId, String role) {
		return labelDao.findLabelJsonByBaseIdAndRole(baseId, role);
	}
}
